package leetcode.editor.cn;
//[123]买卖股票的最佳时机 III
public class BestTimeToBuyAndSellStockIii123{
public static void main(String[] args) {
   Solution solution = new BestTimeToBuyAndSellStockIii123().new Solution();
   int res = solution.maxProfit(new int[]{3,3,5,0,0,3,1,4});
    System.err.println("BestTimeToBuyAndSellStockIii123:main:res:"+res);
}

  //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    //dp buy 时对应k
    //dp 数组的遍历顺序 以 base case 为起点，逐步向结果靠近。
    public int maxProfitDP(int[] prices) {
        if (prices == null || prices.length < 2)return 0;
        int len = prices.length;

        int [][][] dp = new int[len][3][2];

        //原始的状态转移方程，没有可化简的地方
        //dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
        //dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
        for (int i = 0; i < prices.length; i++) {

            for (int k = 0; k < 3; k++) {
                if (k == 0){//初始值
                    dp [i][k][0] = 0;
                    dp [i][k][1] = Integer.MIN_VALUE;
                    continue;
                }
                if (i==0){//初始值
                    dp [i][k][0] = 0;
                    dp [i][k][1] = -prices[0];
                    continue;
                }
                dp[i][k][0] = Math.max(dp[i-1][k][0],dp[i-1][k][1] + prices[i]);
                dp[i][k][1] = Math.max(dp[i-1][k][1],dp[i-1][k-1][0] - prices[i]);
            }
        }

        return dp[len-1][2][0];
    }

//这里k取值范围比较小，所以可以不用 for 循环，
// 直接把 k = 1 和 2 的情况全部列举出来也可以：

// 状态转移方程：
// dp[i][2][0] = max(dp[i-1][2][0], dp[i-1][2][1] + prices[i])
// dp[i][2][1] = max(dp[i-1][2][1], dp[i-1][1][0] - prices[i])
// dp[i][1][0] = max(dp[i-1][1][0], dp[i-1][1][1] + prices[i])
// dp[i][1][1] = max(dp[i-1][1][1], -prices[i])

      // 空间复杂度优化版本
      int maxProfit(int[] prices) {
          // base case
          int dp_i10 = 0, dp_i11 = Integer.MIN_VALUE;
          int dp_i20 = 0, dp_i21 = Integer.MIN_VALUE;
          for (int price : prices) {
              dp_i20 = Math.max(dp_i20, dp_i21 + price);
              dp_i21 = Math.max(dp_i21, dp_i10 - price);
              dp_i10 = Math.max(dp_i10, dp_i11 + price);
              dp_i11 = Math.max(dp_i11, -price);
          }
          return dp_i20;
      }
}
//leetcode submit region end(Prohibit modification and deletion)

}